const { enc: { Utf8 }, Rabbit: { encrypt, decrypt } } = require('crypto-js')

const input = require('../utils/input')
const reader = require('../utils/reader')
const writer = require('../utils/writer')
const checker = require('../utils/checker')
const { info, warn } = require('../utils/output')
const { userinfoPath } = require('../utils/path')
const { locale, dateFilter, getTimeByDuration } = require('../utils/date')
const {
  isValidInput,
  isValidUsername,
  isValidPassword,
  isValidUserInfo,
  isValidSubmitParam
} = require('../utils/validator')


// Secret Key
const key = '&)~+\\"?_(;#`$]^-[:@*'

const timeQuestionOptions = {
  locale,
  type: 'date',
  filter: dateFilter,
}

// Yes or No 问题
const alternativeInquirer = message => [{
  message,
  name: 'answer',
  type: 'rawlist',
  choices: [{ name: '是', value: true }, { name: '否', value: false }],
  default: 0
}]

// 账号密码
const userinfoQuestion = [
  {
    name: 'username',
    type: 'input',
    message: '请输入12位学号：',
    validate(val) {
      return isValidUsername(val) || "你这学号有问题啊"
    }
  },
  {
    name: 'userpwd',
    type: 'password',
    message: '请输入你的ISP密码：',
    mask: true,
    validate(val) {
      return isValidPassword(val) || "你这密码保真吗？怎么六位都不到啊"
    }
  }
]

// 时间
const timeQuestion = [
  {
    name: 'leaveTime',
    message: '请选择离校时间：',
    ...timeQuestionOptions
  },
  {
    name: 'returnTime',
    message: '请选择返校时间：',
    ...timeQuestionOptions
  }
]

// 申请临时离校凭证
const submitQuestion = [
  {
    name: 'type',
    type: 'rawlist',
    message: '请选择离校类型：',
    choices: ['兼职实习', '医院就诊', '单位面试', '学习培训', '回家', '其他'],
    default: 0
  },
  {
    name: 'cause',
    type: 'input',
    message: '请输入离校事由：',
    validate(val) {
      return isValidInput(val) || "还没输入呢"
    }
  },
  {
    name: 'destination',
    type: 'input',
    message: '请输入去往地点：',
    validate(val) {
      return isValidInput(val) || "还没输入呢"
    }
  },
  {
    name: 'outProvince',
    type: 'rawlist',
    message: '是否出省',
    choices: [{ name: '是', value: 1 }, { name: '否', value: 0 }],
    default: 1
  },
  {
    name: 'transport',
    type: 'input',
    message: '请输入交通方式：',
    validate(val) {
      return isValidInput(val) || "还没输入呢"
    }
  },
  {
    name: 'defaultDuration',
    type: 'rawlist',
    message: '你可以选择一个默认的离校时长，以后申请将使用此时长',
    choices: [
      { name: '不选择', value: 0 },
      { name: '8小时', value: 8 * 60 * 60 * 1000 },
      { name: '12小时', value: 12 * 60 * 60 * 1000 },
      { name: '24小时', value: 24 * 60 * 60 * 1000 },
      { name: '48小时', value: 48 * 60 * 60 * 1000 },
      { name: '72小时', value: 72 * 60 * 60 * 1000 },
      { name: '1周', value: 24 * 7 * 60 * 60 * 1000 },
      { name: '2周', value: 2 * 24 * 7 * 60 * 60 * 1000 },
    ],
    default: 0
  }
]

// 保存加密后的用户信息到文件
const saveUserinfo = async ({ ...data }) => {
  info('即将在同级目录创建文件保存信息...')
  for (const [k, v] of Object.entries(data)) {
    data[k] = encrypt(v.toString(), key).toString()
  }
  await writer(userinfoPath, JSON.stringify(data))
}

// 获取并保存帐号密码信息
const askBaseinfo = async () => {
  const userinfo = await input(userinfoQuestion)
  await saveUserinfo(userinfo)
  return userinfo
}

// 获取离校和返校时刻 未指定默认离校时长时调用
const askTime = async () => {
  warn('未指定默认离校时长，需要填写以下信息：')
  const { leaveTime, returnTime } = await input(timeQuestion)
  return { leaveTime, returnTime }
}

// 根据离校时长决定获取离校和返校时刻的方式
const getRoundTripTime = async (duration) => {
  return duration ? getTimeByDuration(duration) : await askTime()
}

// 获取并保存提交参数信息
const askSubmitParams = async (params) => {
  const res = await input(submitQuestion)
  const { defaultDuration } = res
  const { leaveTime, returnTime } = await getRoundTripTime(defaultDuration)
  await saveUserinfo({ ...params, ...res })
  return [true, { ...params, ...res, leaveTime, returnTime }]
}

// 询问是否更改信息并保存
const needRewriteUserinfo = async () => {
  const { answer } = await input(alternativeInquirer('需要重新输入信息并保存文件吗？'))
  checker(answer, '', '用户信息不完整')
  const userinfo = await askBaseinfo()
  return userinfo
}

// 验证帐号密码信息 对一些情况做了处理
const checkBaseinfo = async () => {
  info('验证文件信息...')
  let userinfo = null
  try {
    const [fileNotExists, res] = await reader(userinfoPath)
    if (fileNotExists) {
      info('文件不存在，需要输入以下信息')
      userinfo = await askBaseinfo()
    } else {
      for (const [k, v] of Object.entries(res)) {
        res[k] = decrypt(v, key).toString(Utf8)
      }
      userinfo = res
    }
    checker(isValidUserInfo(userinfo), '帐号密码验证完成', '格式有误')
  } catch (e) {
    warn('检测到' + e)
    userinfo = await needRewriteUserinfo()
  }
  return userinfo
}

// 验证提交参数 若不通过可选择是否填写
const checkSubmitParams = async (params) => {
  if (isValidSubmitParam(params)) {
    const { defaultDuration } = params
    const { leaveTime, returnTime } = await getRoundTripTime(defaultDuration)
    return [true, { ...params, leaveTime, returnTime }]
  }
  const { answer } = await input(alternativeInquirer('是否填写申请临时离校的信息？'))
  if (!answer) {
    warn('将不会提交离校凭证申请请求')
    return [false, params]
  }
  const res = await askSubmitParams(params)
  return res
}

// 读取并验证用户信息
const checkUserinfo = async () => {
  // 账号密码部分
  const userinfo = await checkBaseinfo()

  // 提交参数部分
  const res = await checkSubmitParams(userinfo)
  return res
}

module.exports = checkUserinfo